// NewTrainingFramework.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "../Utilities/utilities.h" // if you use STL, please include this line AFTER all other include
#include "Shaders.h"
#include <conio.h>
#include "Globals.h"
#include "LookAtCamera.h"
#include "Model.h"
#include "Skydome.h"
#include "Terrain.h"
#include "Constant.h"
#include "Reflection.h"
#include "Lighting.h"
#include "Fire.h"
#include "Bloom.h"

Shaders myShaders;
Model *womanModel;
Model *marineModel;
Model *PlanetModel;
Skydome *mySkydome;
Reflection *reflectionSkydome;
Lighting *circleLighting;
Model *ufo;
Fire *fire;
//Bloom *sun;

int Init ( ESContext *esContext )
{
	glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f );

	//Setup main camera, it is lookatcamera
	((LookAtCamera*)Globals::MainCamera)->Init(
		Vector3(0.0f, 50.0f, 20.0f),
		Vector3(0.0f, 0.0f, 0.0f),
		Vector3(0.0f, 1.0f, 0.0f),
		3.14f / 4.0f,
		1.0f,
		10000.0f);

	//Create model
	womanModel = new Model();
	womanModel->Init("../Resources/Models/woman1.nfg", "../Resources/Textures/woman1.tga");
	womanModel->Translate(30.0f, 40.0f, 10.0f);
	womanModel->Scale(5.0f, 5.0f, 5.0f);

	//create skydome
	mySkydome = new Skydome();
	mySkydome->Init("../Resources/Models/SkyBox.nfg",
		"../Resources/Textures/Skydome_0.tga",
		"../Resources/Textures/Skydome_1.tga",
		"../Resources/Textures/Skydome_2.tga",
		"../Resources/Textures/Skydome_3.tga",
		"../Resources/Textures/Skydome_4.tga",
		"../Resources/Textures/Skydome_5.tga");
	mySkydome->Scale(3000.0f, 3000.0f, 3000.0f);

	//create terrain
	//Globals::terrain = new Terrain();
	Globals::terrain->Init("../Resources/Textures/heightmap.raw");
	//Globals::terrain->Scale(1.0f, 0.5f, 1.0f);

	//create reflection object
	reflectionSkydome = new Reflection();
	reflectionSkydome->Init("../Resources/Models/Bila.nfg", mySkydome->GetTextureID());
	reflectionSkydome->Scale(0.5f, 0.5f, 0.5f);
	reflectionSkydome->Translate(80.0f, 100.0f, 0.0f);

	circleLighting = new Lighting();
	circleLighting->Init("../Resources/Models/Bila.nfg", "../Resources/Textures/Dirt.tga");
	circleLighting->Scale(0.5f, 0.5f, 0.5f);
	circleLighting->Translate(20.0f, 100.0f, 0.0f);

	ufo = new Model();
	ufo->Init("../Resources/Models/Bila.nfg", "../Resources/Textures/Dirt.tga");
	ufo->Scale(0.5f, 0.5f, 0.5f);
	ufo->Translate(-40.0f, 100.0f, 0.0f);

	fire = new Fire();
	fire->Init("../Resources/Models/fire.nfg", "../Resources/Textures/fire3.tga", "../Resources/Textures/fire_mask.tga", "../Resources/Textures/DisplacementMap.tga");
	fire->Scale(3.0f, 3.0f, 3.0f);
	fire->Translate(30.0f, 40.0f, 0.0f);

	//sun = new Bloom();
	//sun->Init("../Resources/Models/Bila.nfg", "../Resources/Textures/Rock.tga");
	//sun->Scale(0.2f, 0.2f, 0.2f);
	//sun->Translate(-40.0f, 190.0f, 0.0f);

	//creation of shaders and program 
	return myShaders.Init("../Resources/Shaders/TriangleShaderVS.vs", "../Resources/Shaders/TriangleShaderFS.fs");

}

void Draw ( ESContext *esContext )
{
	glClear(GL_COLOR_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);

	glUseProgram(myShaders.program);
	//womanModel->Draw(esContext);
	//marineModel->Draw(esContext);
	mySkydome->Draw(esContext);
	Globals::terrain->Draw(esContext);
	reflectionSkydome->Draw(esContext);
	circleLighting->Draw(esContext);
	ufo->Draw(esContext);
	fire->Draw(esContext);
	//sun->Draw(esContext);

	eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
}

void Update ( ESContext *esContext, float deltaTime )
{
	Globals::MainCamera->Update(esContext, deltaTime);
	womanModel->Update(esContext, deltaTime);
	//marineModel->Update(esContext, deltaTime);
	//mySkydome->Update(esContext, deltaTime);
	Globals::terrain->Update(esContext, deltaTime);
	reflectionSkydome->Update(esContext, deltaTime);
	circleLighting->Update(esContext, deltaTime);
	ufo->Update(esContext, deltaTime);
	fire->Update(esContext, deltaTime);
	//sun->Update(esContext, deltaTime);
	//ufo->RotateX(0.02f);
}

void Key ( ESContext *esContext, unsigned char key, bool bIsPressed)
{
	GLfloat offset = 3.0f;
	switch(key)
	{
	case 'Z':
		{
			Globals::MainCamera->MoveDown(offset*5.0f);
		}
		break;
	case 'X':
		{
			Globals::MainCamera->MoveUp(offset*5.0f);
		}
		break;
	case 'A':
		{
			Globals::MainCamera->MoveLeft(offset);
		}
		break;
	case 'D':
		{
			Globals::MainCamera->MoveRight(offset);
		}
		break;
	case 'W':
		{
			Globals::MainCamera->MoveForward(offset);
		}
		break;
	case 'S':
		{
			Globals::MainCamera->MoveBackward(offset);
		}
		break;
	case 39:
		{
			Globals::MainCamera->RotateLeft(0.1f);
		}
		break;
	case 37:
		{
			Globals::MainCamera->RotateRight(0.1f);
		}
		break;
	case 40:
		{
			Globals::MainCamera->RotateDown(0.1f);
		}
		break;
	case 38:
		{
			Globals::MainCamera->RotateUp(0.1f);
		}
		break;
	default:
		break;
	};
}

void CleanUp()
{
	SAFE_DEL(Globals::MainCamera);
	SAFE_DEL(womanModel);
	//SAFE_DEL(marineModel);
	SAFE_DEL(mySkydome);
	SAFE_DEL(Globals::terrain);
	SAFE_DEL(reflectionSkydome);
	SAFE_DEL(circleLighting);
	SAFE_DEL(ufo);
	SAFE_DEL(fire);
	//SAFE_DEL(sun);
}

int _tmain(int argc, _TCHAR* argv[])
{
	//identifying memory leaks
	_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); 

	ESContext esContext;

    esInitContext ( &esContext );

	esCreateWindow ( &esContext, "Hello Triangle", Globals::screenWidth, Globals::screenHeight, ES_WINDOW_RGB | ES_WINDOW_DEPTH);

	if ( Init ( &esContext ) != 0 )
		return 0;

	esRegisterDrawFunc ( &esContext, Draw );
	esRegisterUpdateFunc ( &esContext, Update );
	esRegisterKeyFunc ( &esContext, Key);

	esMainLoop ( &esContext );

	//releasing OpenGL resources
	CleanUp();

	printf("Press any key...\n");
	_getch();

	return 0;
}

